#include <head.h>
// 定义一个函数，用于递归地打印目录树
int my_tree(char *file_name);

int main(int argc, char const *argv[])
{
    my_tree("test");
    return 0;
}

int my_tree(char *dir_name)
{
    DIR *dir = opendir(dir_name); // 尝试打开目录
    if (dir == NULL)
    {
        perror("无法打开目录"); // 如果打开失败，打印错误信息
        return 1;               // 返回错误码
    }

    struct dirent *entry;  // 用于存储readdir()返回的文件目录项
    const char *file;      // 用于存储文件路径的指针
    struct stat file_stat; // 用于存储文件状态信息的结构体
    char file_path[1024];  // 用于存储完整文件路径的缓冲区

    while ((entry = readdir(dir)) != NULL) // 遍历目录下的所有项
    {
        // 如果是目录且不是"."或".."，则递归调用my_tree
        if (entry->d_type == DT_DIR && strcmp(entry->d_name, "..") && strcmp(entry->d_name, "."))
        {
            snprintf(file_path, sizeof(file_path), "%s/%s", dir_name, entry->d_name);
            my_tree(file_path);
        }

        // 无论文件类型，都构建完整路径并获取其状态
        snprintf(file_path, sizeof(file_path), "%s/%s", dir_name, entry->d_name);
        file = file_path;

        int num = stat(file, &file_stat); // 获取文件状态
        if (num == -1)
        {
            perror("stat"); // 如果获取失败，打印错误信息
            return -1;      // 返回错误码
        }

        // 根据文件类型打印不同的前缀
        switch (file_stat.st_mode & S_IFMT)
        {
        case S_IFREG:
            printf("-");
            break;
        case S_IFDIR:
            printf("d");
            break;
        case S_IFCHR:
            printf("c");
            break;
        case S_IFBLK:
            printf("b");
            break;

        case S_IFIFO:
            printf("p");
            break;

        case S_IFSOCK:
            printf("s");
            break;
        case S_IFLNK:
            printf("l");
            break;
        default:
            printf("未知文件类型");
            break;
        }

        // 打印文件权限
        printf((file_stat.st_mode & S_IRUSR) ? "r" : "-");
        printf((file_stat.st_mode & S_IWUSR) ? "w" : "-");
        printf((file_stat.st_mode & S_IXUSR) ? "x" : "-");
        printf((file_stat.st_mode & S_IRGRP) ? "r" : "-");
        printf((file_stat.st_mode & S_IWGRP) ? "w" : "-");
        printf((file_stat.st_mode & S_IXGRP) ? "x" : "-");
        printf((file_stat.st_mode & S_IROTH) ? "r" : "-");
        printf((file_stat.st_mode & S_IWOTH) ? "w" : "-");
        printf((file_stat.st_mode & S_IXOTH) ? "x" : "-");

        // 打印链接数、所有者、所属组、大小、最后访问时间
        printf(" %lu ", file_stat.st_nlink);
        struct passwd *user = getpwuid(file_stat.st_uid); // 获取所有者用户名
        printf(" %s ", user->pw_name);
        struct group *user_group = getgrgid(file_stat.st_gid); // 获取所属组名
        printf(" %s ", user_group->gr_name);
        printf(" %ld\t ", file_stat.st_size);
        time_t t = file_stat.st_atime;         // 获取最后访问时间
        struct tm *local_time = localtime(&t); // 转换为本地时间
        printf(" %d月 %d日 %d:%d \t", local_time->tm_mon + 1, local_time->tm_mday, local_time->tm_hour, local_time->tm_min);
        printf(" %s \n", file); // 打印文件名或目录名
    }

    closedir(dir); // 关闭目录流
    return 0;      // 返回
}